import { Client } from 'boardgame.io/client';
import { CSPR } from './Game';
import _ from 'lodash';
import { IBehaviour, IPlayer } from './types';

interface IBehaviourRecord {
  behaviour: IBehaviour,
  score: number,
  id: number,
  positions: number[],
}

const client = Client({
  game: CSPR,
});

function get_behaviour(): IBehaviour {
  return {
    protective: _.random(10),
    greedy: _.random(10),
    protective_growth: _.random(3),
    preferences: [0,0,0,0,0,0,0,0].map(()=>_.random(1,9)),
  };
}

function mutate(behaviour: IBehaviour): IBehaviour {
  return {
    ...behaviour,
    protective: Math.abs(behaviour.protective - 1 + _.random(3)),
    greedy: Math.abs(behaviour.greedy - 1 + _.random(3)),
    protective_growth: Math.abs(behaviour.protective_growth - 1 + _.random(3)),
    preferences: behaviour.preferences.map(x => Math.abs((x - 1 + _.random(3)))),
  }
}

let records: IBehaviourRecord[] = []
for (let i=0; i<300; i++) {
  records.push({
    behaviour: get_behaviour(),
    score: 0,
    positions: [0,0,0,0],
    id: i,
  });
}

function get_result(records: IBehaviourRecord[], players: IPlayer[]) {
  let sort_by_score = players.sort((a,b) => b.score - a.score);
  let scores = [3, -1, -1, -1];
  for (let i=0; i<4; i++) {
    let player = sort_by_score[i];
    let record = records.find(r => r.behaviour == player.preset_ai_behaviour);
    if (record != undefined) {
      record.score += scores[i];
      record.positions[i] += 1;
    }
    else {
      console.log("RecordNotFoundError: record not found.");
    }
  }
}

function process_record(record: IBehaviourRecord) {
  return JSON.stringify({
    ...record,
    position_rate: [0,1,2,3].map(x => record.positions[x]/_.sum(record.positions)),
  });
}

client.start();

for (let R=0; R<3002; R++) {
  for (let T=0; T<75; T++) {
    client.reset();
    client.moves.setup_scenario(R+32);
    client.moves.set_ai_players(4);
    client.moves.set_ai_behaviours(records.slice(T*4,(T+1)*4).map(r => r.behaviour));
    while (client.getState()!.G.should_finished == false) {
      for (let i=0; i<6; i++) {
        client.moves.ai_moves();
        client.moves.add_action();
      }
      while (client.getState()!.G.phase == "action") {
        client.moves.ai_act(0);
      }
    }
    get_result(records, client.getState()!.G.players.map(p=>({...p})));
  }
  console.log("R", R);

  if (R % 500 === 499) {
    let sorted_records = [...records].sort((a,b) => (b.score - a.score));
    console.log("Tops");
    console.log(sorted_records.slice(0,5).map(process_record));
    records.sort((a,b) => (b.score - a.score));
    for (let i=0; i<150; i++) {
      records[i+150].behaviour = mutate(records[i].behaviour);
      records[i].score = 5;
      records[i].positions = [0,0,0,0];
      records[i+150].score = -5;
      records[i+150].positions = [0,0,0,0];
    }
  }
  // Random Shuffle
  // records = _.shuffle(records);
  // Enable Swiss
  records.sort((a,b) => (b.score - a.score));
}

console.log("Finished");